package tgc.edu.tms.web.controller;

import java.util.Collections;
import java.util.HashSet;
import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import tgc.edu.tms.custom.AjaxResult;
import tgc.edu.tms.custom.BaseForm;
import tgc.edu.tms.custom.CommonController;
import tgc.edu.tms.entity.ClassSchedule;
import tgc.edu.tms.entity.Classroom;
import tgc.edu.tms.entity.EducationalPlanner;
import tgc.edu.tms.entity.EducationalRecord;
import tgc.edu.tms.entity.Jcb;
import tgc.edu.tms.entity.Schedule;
import tgc.edu.tms.entity.TbClass;
import tgc.edu.tms.entity.TbclassClassroom;
import tgc.edu.tms.entity.Teacher;
import tgc.edu.tms.service.ClassScheduleService;
import tgc.edu.tms.service.ClassroomService;
import tgc.edu.tms.service.EducationalPlannerService;
import tgc.edu.tms.service.EducationalRecordService;
import tgc.edu.tms.service.JcbService;
import tgc.edu.tms.service.ScheduleService;
import tgc.edu.tms.service.TbclassClassroomService;
import tgc.edu.tms.web.form.AgcsFrom;
@Controller
@RequestMapping(value = "/agcs")
public class AgcsController extends CommonController<Schedule, Integer, BaseForm<Integer>>{
	@Autowired
	private JcbService jcbservice;
	@Autowired
	private ClassroomService classroomService;
	@Autowired
	private EducationalPlannerService epservice;
	@Autowired
	private ClassScheduleService classScheduleservice;
	@Autowired
	private ScheduleService classservice;
	@Autowired
	private TbclassClassroomService tcservice;
	@Autowired
	private EducationalRecordService erecordservice;
	
	@RequestMapping(value="getMax")
	@ResponseBody
	public String getMax() {
		String yes="yes";
		List<EducationalRecord> list=erecordservice.findAll();
		if(list.size()<1) {
			yes="no";
		}
		return yes;
	}
	
	@RequestMapping(value="/eddelete")
	@ResponseBody
	public Object eddelete(Integer id) {
		try {
			erecordservice.deleteById(id);
			return new AjaxResult("数据删除成功");
		} catch (Exception e) {
			return new AjaxResult(false,"数据删除失败");
		}
	}
	@RequestMapping(value="/timedelete")
	@ResponseBody
	public Object timedelete(Integer id) {
		try {
			tcservice.deleteById(id);
			return new AjaxResult("数据删除成功");
		} catch (Exception e) {
			return new AjaxResult(false,"数据删除失败");
		}
	}
	@RequestMapping(value="/myagcs")
	public String myagcs() {
		return "agcs/myagcs";
	}
	@RequestMapping(value="/findAlls")
	@ResponseBody
	public Object findAll(String search) {
		Specification<EducationalRecord> spec = new Specification<EducationalRecord>() {
			private static final long serialVersionUID = 1L;

			@Override
			public Predicate toPredicate(Root<EducationalRecord> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				HashSet<Predicate> rules = new HashSet<>();
				
				if (StringUtils.hasText(search)) {
					Predicate xnxq = cb.like(root.get("ed").get("schoolyear").get("xnxq"),"%" + search + "%");
					Predicate kcmc = cb.like(root.get("ed").get("curriculum").get("kcmc"),"%" + search + "%");
					Predicate kcdm = cb.like(root.get("ed").get("curriculum").get("kcdm"),"%" + search + "%");
					Predicate name = cb.like(root.get("ed").get("teacher").get("name"),"%" + search + "%");
					Predicate year = cb.like(root.get("ed").get("curriculum").get("profession").get("year"),"%" + search + "%");
					Predicate bj = cb.like(root.get("ed").get("searcherbanji"),"%" + search + "%");
					Predicate jslx = cb.like(root.get("ed").get("jslx"),"%" + search + "%");
					Predicate records = cb.like(root.get("records"),"%" + search + "%");



					
					Predicate rules2 = cb.or(xnxq,kcmc,kcdm,name,year,bj,jslx,records);
					rules.add(rules2);
				}
				return cb.and(rules.toArray(new Predicate[rules.size()]));
			}
		};
		List<EducationalRecord> list=erecordservice.findAll(spec);
		return list;
	}
	
	@RequestMapping(value="/findAllTime")
	@ResponseBody
	public Object findAllTime(String search) {
		Specification<TbclassClassroom> spec = new Specification<TbclassClassroom>() {
			private static final long serialVersionUID = 1L;

			@Override
			public Predicate toPredicate(Root<TbclassClassroom> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				HashSet<Predicate> rules = new HashSet<>();
				
				if (StringUtils.hasText(search)) {
					Predicate xnxq = cb.like(root.get("classroom").get("serialNumber"),"%" + search + "%");
					Predicate kcmc = cb.like(root.get("classroom").get("type").get("name"),"%" + search + "%");
					Predicate name = cb.like(root.get("jcb").get("xq"),"%" + search + "%");
					Predicate year = cb.like(root.get("jcb").get("jcsj"),"%" + search + "%");
					Integer serarchint=null;
					try {
						serarchint=Integer.parseInt(search);
					} catch (Exception e) {
						serarchint=null;
					}
					Predicate rules2 = cb.or(xnxq,kcmc,name,year);
					if(serarchint!=null) {
						Predicate kcdm = cb.equal(root.get("classroom").get("capacity"),serarchint);	
						rules2= cb.or(kcdm);
					}
					rules.add(rules2);
				}
				return cb.and(rules.toArray(new Predicate[rules.size()]));
			}
		};
		Sort sort = new Sort(Direction.DESC, "classroom");
		List<TbclassClassroom> ag=tcservice.findAll(spec,sort);
		return ag;
	}
	/**
	 * 自动生成课表
	 *
	* 1.安排的课程和教室类型要相同ok
	* 2.教室人数要大于等于  安排的班级人数（已考虑合班）ok
	* 3.同时间一个班的两个课程不能安排在一个时间点上上课
	* 4.同一个教师所上的所有课程不能安排在同一时间上；
	* 5.一班级的同一门课程的上课时间尽量间隔均匀些。
	* 例如，某班级的高等数学课在一周内需要安排俩次授课。两次授课时间的安排时间就需要尽量间隔一天或者一天以上；
	* 
	 * @param from
	 * @return
	 */
	@RequestMapping("/schedule")
	@ResponseBody
	public Object AgcsSchedule(AgcsFrom from) {
		/***
		 *   修改节次表
		 *   按照用户需求
		 */
		List<Jcb> jcb = jcb(from);
		/***
		 *  取出所有教室
		 * 
		 */
		List<Classroom> classroom=classroomService.findAll();
		/***
		 * 	取出这一学年全校所有教学计划
		 */
		List<EducationalPlanner> eps=epservice.findBySchoolyearId(from.getSchoolyearID());
		//打乱三张表顺序
		Collections.shuffle(eps);//学期计划
		Collections.shuffle(jcb);//节次表
		Collections.shuffle(classroom);//教室 最终取出教室容量 和教室类型
		/***
		 * 前期准备工作
		 * 删除防止重复点击，首先删除已生成的报废的表
		 */
		erecordservice.deleteAll();			//删除所有未分配的课表
		classservice.deleteByScyearId(from.getSchoolyearID());
		
		
		
		int sums=0;
		for(int e=0;e< eps.size() ;e++) {
			EducationalPlanner sum = eps.get(e);
			sums=sums+sum.getCurriculum().getZhouxs();
		}
		if(sums>(jcb.size()*classroom.size())) {
			return "错误,需要安排的课程无法完全编排，您可以考录增加教室，增加节次时间，或者合班上课！";
		}
		tcservice.deleteAlls();//删除所有数据表
		tcservice.findByList(jcb,classroom);//新增所有需要的数据
		
		
		for (int k = 0; k < eps.size(); k++) {
			EducationalPlanner e = eps.get(k);
			/***
			 * 确定这门课程能安排在那些时间上课
			 * 
			 */
			List<TbclassClassroom> ag=tcservice.findAll();
			
			List<TbClass> etbclass = e.getTbclass();//取出这个班所有的班级3	//有哪些班级
			//取出班级相关的所有相关的课表 重要是使用节次表判断同时间是否有课
			List<Schedule> classSchedules=classservice.findByClasses(etbclass,from);
			for (int j = 0; j < classSchedules.size(); j++) {
				Schedule classSchedule = classSchedules.get(j);
				//*所有已安排过的课表--这个班级 即这里面所有的节次ID不能使用
				
				for (int i = 0; i < ag.size(); i++) {
					TbclassClassroom tbclassing = ag.get(i);
					
					if(tbclassing.getJcb().getXq().equals(classSchedule.getXq())&&tbclassing.getJcb().getJcsj().equals(classSchedule.getJcsj())) {
						ag.remove(i);
						i--;
					}
					
				}
			}
			if(ag.size()<(e.getCurriculum().getZhouxs())) {//这门课程无法安排
				EducationalRecord entity=new EducationalRecord();
				entity.setEd(e);
				entity.setRecords("此课程内的班级课程已满，无法安排此课程！");
				erecordservice.save(entity);
				continue;
			}
			//取出老师 把同老师的在一时间点上的所有时间删除掉！
			Teacher teacher = e.getTeacher();
			List<Schedule> teacherSchedules=classservice.findByTeachers(teacher,from);
			for (int l = 0; l < teacherSchedules.size(); l++) {
				Schedule classSchedule2 = teacherSchedules.get(l);
				for (int i = 0; i < ag.size(); i++) {
					TbclassClassroom tbclassing = ag.get(i);
					
					if(tbclassing.getJcb().getXq().equals(classSchedule2.getXq())&&tbclassing.getJcb().getJcsj().equals(classSchedule2.getJcsj())) {
						ag.remove(i);
						i--;
					}
					
				}
			}
			
			if(ag.size()<(e.getCurriculum().getZhouxs())) {//这门课程无法安排
				EducationalRecord entity=new EducationalRecord();
				entity.setEd(e);
				entity.setRecords("此课程内的老师在同时间内课程已满，无法安排此课程！");
				erecordservice.save(entity);
				continue;
			}
			
			for (int i = 0; i < ag.size(); i++) {
				TbclassClassroom a = ag.get(i);
				
				String jslx = e.getJslx(); 	//从教学计划中取出教室类型
				String classroomjslx=a.getClassroom().getType().getName();	//从教室中取出的教室类型
				if(!jslx.equals(classroomjslx)) {
					ag.remove(i);
					i--;
					continue;
				}
				Integer classroomcapacity=a.getClassroom().getCapacity();//取出教室的容量
				Integer tbcapacity=0;					//取出班级的所有人数 （包括合班级）
				for (TbClass tbClass : e.getTbclass()) {
					tbcapacity = tbcapacity + tbClass.getNumber();
				}
				if(classroomcapacity<tbcapacity) {
					ag.remove(i);
					i--;
					continue;
				}
				
			}
			Collections.shuffle(ag);
			
			if(ag.size()<(e.getCurriculum().getZhouxs())) {//这门课程无法安排
				EducationalRecord entity=new EducationalRecord();
				entity.setEd(e);
				entity.setRecords("此课程没有教室可以安排！");
				erecordservice.save(entity);
				continue;
			}
			
			//这里一门课程里的几门课程随机分部，可能存在不均匀
			Integer zhouxs = e.getCurriculum().getZhouxs();//周学时
		 	Integer classId = classservice.findMaxId();
		 	//当课程需要安排的安排两门课时，则需要删除掉低于两门课程的教室删除掉
		 	if(zhouxs>1) {
				for (int example = 0; example < ag.size(); example++) {
					TbclassClassroom y1 = ag.get(example);
					int su=0;
					for (int traverse = 0; traverse < ag.size(); traverse++) {
						TbclassClassroom y2 = ag.get(traverse);
						if(y1.getClassroom().getId()==y2.getClassroom().getId()) {
							su=su+1;
						}
					}
					if(su<e.getCurriculum().getZhouxs()) {
						ag.remove(example);
						example--;
					}
					
				}
		 	}
		 	if(ag.size()<(e.getCurriculum().getZhouxs())) {//这门课程无法安排
				EducationalRecord entity=new EducationalRecord();
				entity.setEd(e);
				entity.setRecords("无法在一星期内同教室安排不同时间的课程表");
				erecordservice.save(entity);
				continue;
			}
		 	//取出
		 	Integer tbcapacitys=0;					//取出班级的所有人数 （包括合班级）
			for (TbClass tbClass : e.getTbclass()) {
				tbcapacitys = tbcapacitys + tbClass.getNumber();
			}
		 	Integer classroomIds=null;
		 	Integer p=0;
			for(int in=0; in<zhouxs ;in++ ) {
				for(int v=0;v<ag.size();v++) {
					TbclassClassroom t = ag.get(v);
					if(classroomIds==null) {
						for (TbclassClassroom tbclassClassroom : ag) {//找出最适合安排教室的教室
							Integer sql=tbclassClassroom.getClassroom().getCapacity();//取出教室的容量
							Integer sum=sql-tbcapacitys;
							if(sum<p||p==0) {
								classroomIds=tbclassClassroom.getClassroom().getId();
								System.out.println(classroomIds);
								p=sum;
							}
						}
					}
					if(t.getClassroom().getId()==classroomIds) {
						Schedule classSchedube=new Schedule() ;
						classId=classId+1;
						classSchedube.setId(classId);
						//ep-c
						
						classSchedube.setKcmc(e.getKcmc());
						classSchedube.setKcdm(e.getKcdm());
						classSchedube.setZongxs(e.getZongxs());
						classSchedube.setXf(e.getXf());
						classSchedube.setJsxs(e.getJsxs());
						classSchedube.setSyxs(e.getSyxs());
						classSchedube.setSjxs(e.getSjxs());
						classSchedube.setQtxs(e.getQtxs());
						classSchedube.setKclb(e.getKclb());
						classSchedube.setZhouxs(e.getZhouxs());
						classSchedube.setKhfs(e.getKhfs());
						classSchedube.setKkxq(e.getCurriculum().getKkxq());
						classSchedube.setProfession(e.getCurriculum().getProfession());
						//ep
						classSchedube.setQszc(e.getQszc());
						classSchedube.setJszc(e.getJszc());
						classSchedube.setJslx(e.getJslx());
						classSchedube.setTeacher(e.getTeacherName());
						classSchedube.setXnxq(e.getXnxq());
						classSchedube.setTbclass(e.getBj());
						classSchedube.setXmh(e.getXmh());
						
						//上课 时间 节次
						classSchedube.setJcsj(t.getJcb().getJcsj());
						classSchedube.setXq(t.getJcb().getXq());
						
						//classroom教室
						classSchedube.setLocation(t.getClassroom().getLocation());
						classSchedube.setFloor(t.getClassroom().getFloor());
						classSchedube.setSerialNumber(t.getClassroom().getSerialNumber());
						classSchedube.setCapacity(t.getClassroom().getCapacity());
						classSchedube.setType(t.getClassroom().getType());
						
						
						/*String searcherclass="";
						for (TbClass tbClass : e.getTbclass()) {
							searcherclass = searcherclass + tbClass.getName() + ",";
						}
						if (searcherclass != "") {
							String str = searcherclass.substring(0, searcherclass.length() - 1);
							classSchedube.setSearcherclass(str);
						}*/
						classservice.save(classSchedube);
						tcservice.deleteById(t.getId());
						ag.remove(v); 
						v--;
						break;
					}
				}
			}
		}
		List<EducationalRecord> list=erecordservice.findAll();
		return list;
	}

	private List<Jcb> jcb(AgcsFrom from) {
		List<Jcb> jcb1=jcbservice.findAll();
		if(from.getSchedule()==1) {
			for (int i = 0; i < jcb1.size(); i++) {
				Jcb jcb = jcb1.get(i);
				if("9-10".equals(jcb.getJcsj())) {
					jcb1.remove(i);
					i--;
					continue;
				}
				if("星期六".equals(jcb.getXq())) {
					jcb1.remove(i);
					i--;
					continue;
				}
				if("星期日".equals(jcb.getXq())) {
					jcb1.remove(i);
					i--;
					continue;
				}
			}
		}else if(from.getSchedule()==2) {
			for (int i = 0; i < jcb1.size(); i++) {
				Jcb jcb = jcb1.get(i);
				if("9-10".equals(jcb.getJcsj())) {
					jcb1.remove(i);
					i--;
					continue;
				}
			}
		}else if(from.getSchedule()==3) {
			for (int i = 0; i < jcb1.size(); i++) {
				Jcb jcb = jcb1.get(i);
				if("星期六".equals(jcb.getXq())) {
					jcb1.remove(i);
					i--;
					continue;
				}
				if("星期日".equals(jcb.getXq())) {
					jcb1.remove(i);
					i--;
					continue;
				}
			}
		}
		return jcb1;
	}
	@RequestMapping(value="/agcstest")
	@ResponseBody
	private String schedule() {
		List<ClassSchedule> ClassSchedule = classScheduleservice.findAll();
		Integer findMaxId = classservice.findMaxId();
		for (int i = 0; i < ClassSchedule.size(); i++,++findMaxId) {
			ClassSchedule t=ClassSchedule.get(i);
			EducationalPlanner e = t.getEp();
			
			Schedule classSchedube=new Schedule();
			classSchedube.setId(findMaxId);
			//ep-c
			classSchedube.setKcmc(e.getKcmc());
			classSchedube.setKcdm(e.getKcdm());
			classSchedube.setZongxs(e.getZongxs());
			classSchedube.setXf(e.getXf());
			classSchedube.setJsxs(e.getJsxs());
			classSchedube.setSyxs(e.getSyxs());
			classSchedube.setSjxs(e.getSjxs());
			classSchedube.setQtxs(e.getQtxs());
			classSchedube.setKclb(e.getKclb());
			classSchedube.setZhouxs(e.getZhouxs());
			classSchedube.setKhfs(e.getKhfs());
			classSchedube.setKkxq(e.getCurriculum().getKkxq());
			classSchedube.setProfession(e.getCurriculum().getProfession());
			//ep
			classSchedube.setQszc(e.getQszc());
			classSchedube.setJszc(e.getJszc());
			classSchedube.setJslx(e.getJslx());
			classSchedube.setTeacher(e.getTeacherName());
			classSchedube.setXnxq(e.getXnxq());
			classSchedube.setTbclass(e.getBj());
			classSchedube.setXmh(e.getXmh());
			
			//上课 时间 节次
			classSchedube.setJcsj(t.getJcb().getJcsj());
			classSchedube.setXq(t.getJcb().getXq());
			
			//classroom教室
			classSchedube.setLocation(t.getClassroom().getLocation());
			classSchedube.setFloor(t.getClassroom().getFloor());
			classSchedube.setSerialNumber(t.getClassroom().getSerialNumber());
			classSchedube.setCapacity(t.getClassroom().getCapacity());
			classSchedube.setType(t.getClassroom().getType());
			
			classservice.save(classSchedube);
		}
		return "完成复制";
	}
}
